Skip to content

Conversation

eminyouskn
Copy link
Contributor

Fixes NA

Summary/Motivation:

This PR introduced a new KNITRO direct solver interface.

Changes proposed in this PR:

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

Copy link

codecov bot commented Sep 18, 2025

Codecov Report

❌ Patch coverage is 92.39843% with 58 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.16%. Comparing base (740750d) to head (9e4f8bb).

Files with missing lines Patch % Lines
pyomo/contrib/solver/solvers/knitro/base.py 84.27% 25 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/engine.py 91.92% 23 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/package.py 88.00% 6 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/api.py 85.71% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/direct.py 96.87% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/solution.py 96.66% 1 Missing ⚠️
pyomo/contrib/solver/solvers/knitro/utils.py 99.03% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3707      +/-   ##
==========================================
- Coverage   89.18%   89.16%   -0.03%     
==========================================
  Files         896      906      +10     
  Lines      103725   104488     +763     
==========================================
+ Hits        92508    93166     +658     
- Misses      11217    11322     +105     
Flag Coverage Δ
builders ?
default 85.81% <92.26%> (?)
expensive 35.76% <41.67%> (?)
linux 86.64% <39.73%> (-2.30%) ⬇️
linux_other 86.64% <39.73%> (-0.35%) ⬇️
osx 82.81% <39.73%> (-0.32%) ⬇️
win 84.89% <39.73%> (-0.34%) ⬇️
win_other 84.89% <39.73%> (-0.34%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mrmundt
Copy link
Contributor

mrmundt commented Sep 19, 2025

Hi @eminyouskn - okay, so, the tests are running but a large number of them are failing. Here is part of the stacktrace:

19:55:28 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
19:55:28 pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:1963: in test_variables_elsewhere
19:55:28     self.assertAlmostEqual(res.incumbent_objective, 1)
19:55:28 E   AssertionError: 1.0000008993019858 != 1 within 7 places (8.993019857683748e-07 difference)
19:55:28 ----------------------------- Captured stdout call -----------------------------
19:55:28 
19:55:28 =======================================
19:55:28 *** NO CHECK MADE FOR LICENSE ***
19:55:28          Artelys Knitro 15.0.0
19:55:28 =======================================
19:55:28 
19:55:28 Knitro using 1 thread.
19:55:28 No start point provided -- Knitro computing one.
19:55:28 
19:55:28 Knitro performing finite-difference gradient computation with 1 thread.
19:55:28 Knitro presolve eliminated 0 variables and 0 constraints.
19:55:28 
19:55:28 concurrent_evals         0
19:55:28 feastol                  1e-06
19:55:28 feastol_abs              0.001
19:55:28 opttol                   1e-06
19:55:28 opttol_abs               0.001
19:55:28 outlev                   6
19:55:28 Knitro changing hessopt to exact (because the problem is an LP).
19:55:28 The problem is identified as an LP.
19:55:28 Knitro changing algorithm from AUTO to 1.
19:55:28 Knitro changing blasoption from AUTO to 1.
19:55:28 Knitro changing bar_initpt from AUTO to 1.
19:55:28 Knitro changing bar_murule from AUTO to 4.
19:55:28 Knitro changing bar_penaltycons from AUTO to 0.
19:55:28 Knitro changing bar_penaltyrule from AUTO to 2.
19:55:28 Knitro changing bar_switchrule from AUTO to 2.
19:55:28 Knitro changing hessopt from AUTO to 1.
19:55:28 Knitro changing initpt_strategy from AUTO to 1.
19:55:28 Knitro changing linesearch from AUTO to 1.
19:55:28 Knitro changing linsolver from AUTO to 2.
19:55:28 
19:55:28 Problem Characteristics                                 (   Presolved)
19:55:28 -----------------------
19:55:28 Objective goal:  Minimize
19:55:28 Objective type:  linear
19:55:28 Number of variables:                                  2 (           2)
19:55:28     bounded below only:                               0 (           0)
19:55:28     bounded above only:                               0 (           0)
19:55:28     bounded below and above:                          0 (           0)
19:55:28     fixed:                                            0 (           0)
19:55:28     free:                                             2 (           2)
19:55:28 Number of constraints:                                2 (           2)
19:55:28     linear equalities:                                0 (           0)
19:55:28     quadratic equalities:                             0 (           0)
19:55:28     gen. nonlinear equalities:                        0 (           0)
19:55:28     linear one-sided inequalities:                    2 (           2)
19:55:28     quadratic one-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear one-sided inequalities:            0 (           0)
19:55:28     linear two-sided inequalities:                    0 (           0)
19:55:28     quadratic two-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear two-sided inequalities:            0 (           0)
19:55:28 Number of nonzeros in Jacobian:                       4 (           4)
19:55:28 Number of nonzeros in Hessian:                        0 (           0)
19:55:28 
19:55:28 Knitro using the Interior-Point/Barrier Direct algorithm.
19:55:28 
19:55:28   Iter     fCount     Objective      FeasError   OptError    ||Step||    CGits 
19:55:28 --------  --------  --------------  ----------  ----------  ----------  -------
19:55:28        0         5    1.000000e-08   2.314e+00
19:55:28        1         7    1.000000e-08   2.314e+00   4.975e-01   1.652e+00        0
19:55:28        2         9    1.267867e+00   0.000e+00   1.336e-01   1.827e+00        0
19:55:28        3        11    1.001339e+00   0.000e+00   6.715e-04   2.665e-01        0
19:55:28        4        13    1.000001e+00   0.000e+00   4.509e-07   1.338e-03        0
19:55:28 
19:55:28 EXIT: Optimal solution found.
19:55:28 
19:55:28 Final Statistics
19:55:28 ----------------
19:55:28 Final objective value               =   1.00000089930199e+00
19:55:28 Final feasibility error (abs / rel) =   0.00e+00 / 0.00e+00
19:55:28 Final optimality error  (abs / rel) =   4.51e-07 / 4.51e-07
19:55:28 # of iterations                     =          4 
19:55:28 # of CG iterations                  =          0 
19:55:28 # of function evaluations           =         15
19:55:28 # of gradient evaluations           =          0
19:55:28 # of Hessian evaluations            =          0
19:55:28 Total program time (secs)           =       0.00132 (     0.002 CPU time)
19:55:28 Time spent in evaluations (secs)    =       0.00053
19:55:28 
19:55:28 Constraint Vector 		     Lagrange Multipliers
19:55:28 ----------------- 		     ---------------------
19:55:28 c[       0] =  -9.01802131636e-07,   lambda[       0] =                 0.5
19:55:28 c[       1] =  -8.96801839678e-07,   lambda[       1] =                 0.5
19:55:28 
19:55:28 Solution Vector
19:55:28 ---------------
19:55:28 x[       0] =        1.0000008993,   lambda[       2] =                   0
19:55:28 x[       1] =       -1.0000000025,   lambda[       3] =                   0
19:55:28 
19:55:28 ===============================================================================
19:55:28 
19:55:28 _________________ TestSolvers.test_with_numpy_5_knitro_direct __________________
19:55:28 
19:55:28 a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_with_numpy_5_knitro_direct>,)
19:55:28 kw = {}
19:55:28 
19:55:28     @wraps(func)
19:55:28     def standalone_func(*a, **kw):
19:55:28 >       return func(*(a + p.args), **p.kwargs, **kw)
19:55:28 
19:55:28 python3.10/site-packages/parameterized/parameterized.py:620: 
19:55:28 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
19:55:28 pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:1576: in test_with_numpy
19:55:28     self.assertAlmostEqual(m.x.value, (b2 - b1) / (a1 - a2))
19:55:28 E   AssertionError: -0.6666663318632648 != -0.6666666666666666 within 7 places (3.3480340178027035e-07 difference)
19:55:28 ----------------------------- Captured stdout call -----------------------------
19:55:28 
19:55:28 =======================================
19:55:28 *** NO CHECK MADE FOR LICENSE ***
19:55:28          Artelys Knitro 15.0.0
19:55:28 =======================================
19:55:28 
19:55:28 Knitro using 1 thread.
19:55:28 No start point provided -- Knitro computing one.
19:55:28 
19:55:28 Knitro performing finite-difference gradient computation with 1 thread.
19:55:28 Knitro presolve eliminated 0 variables and 0 constraints.
19:55:28 
19:55:28 concurrent_evals         0
19:55:28 feastol                  1e-06
19:55:28 feastol_abs              0.001
19:55:28 opttol                   1e-06
19:55:28 opttol_abs               0.001
19:55:28 outlev                   6
19:55:28 Knitro changing hessopt to exact (because the problem is an LP).
19:55:28 The problem is identified as an LP.
19:55:28 Knitro changing algorithm from AUTO to 1.
19:55:28 Knitro changing blasoption from AUTO to 1.
19:55:28 Knitro changing bar_initpt from AUTO to 1.
19:55:28 Knitro changing bar_murule from AUTO to 4.
19:55:28 Knitro changing bar_penaltycons from AUTO to 0.
19:55:28 Knitro changing bar_penaltyrule from AUTO to 2.
19:55:28 Knitro changing bar_switchrule from AUTO to 2.
19:55:28 Knitro changing hessopt from AUTO to 1.
19:55:28 Knitro changing initpt_strategy from AUTO to 1.
19:55:28 Knitro changing linesearch from AUTO to 1.
19:55:28 Knitro changing linsolver from AUTO to 2.
19:55:28 
19:55:28 Problem Characteristics                                 (   Presolved)
19:55:28 -----------------------
19:55:28 Objective goal:  Minimize
19:55:28 Objective type:  linear
19:55:28 Number of variables:                                  2 (           2)
19:55:28     bounded below only:                               0 (           0)
19:55:28     bounded above only:                               0 (           0)
19:55:28     bounded below and above:                          0 (           0)
19:55:28     fixed:                                            0 (           0)
19:55:28     free:                                             2 (           2)
19:55:28 Number of constraints:                                2 (           2)
19:55:28     linear equalities:                                0 (           0)
19:55:28     quadratic equalities:                             0 (           0)
19:55:28     gen. nonlinear equalities:                        0 (           0)
19:55:28     linear one-sided inequalities:                    2 (           2)
19:55:28     quadratic one-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear one-sided inequalities:            0 (           0)
19:55:28     linear two-sided inequalities:                    0 (           0)
19:55:28     quadratic two-sided inequalities:                 0 (           0)
19:55:28     gen. nonlinear two-sided inequalities:            0 (           0)
19:55:28 Number of nonzeros in Jacobian:                       4 (           4)
19:55:28 Number of nonzeros in Hessian:                        0 (           0)
19:55:28 
19:55:28 Knitro using the Interior-Point/Barrier Direct algorithm.
19:55:28 
19:55:28   Iter     fCount     Objective      FeasError   OptError    ||Step||    CGits 
19:55:28 --------  --------  --------------  ----------  ----------  ----------  -------
19:55:28        0         5    1.000000e-08   3.314e+00
19:55:28        1         7    1.000000e-08   3.314e+00   6.626e-01   2.531e+00        0
19:55:28        2         9    2.552612e+00   0.000e+00   1.372e-01   2.701e+00        0
19:55:28        3        11    2.334430e+00   0.000e+00   6.893e-04   2.386e-01        0
19:55:28        4        13    2.333334e+00   0.000e+00   4.751e-07   1.198e-03        0
19:55:28 
19:55:28 EXIT: Optimal solution found.
19:55:28 
19:55:28 Final Statistics
19:55:28 ----------------
19:55:28 Final objective value               =   2.33333408895725e+00
19:55:28 Final feasibility error (abs / rel) =   0.00e+00 / 0.00e+00
19:55:28 Final optimality error  (abs / rel) =   4.75e-07 / 4.75e-07
19:55:28 # of iterations                     =          4 
19:55:28 # of CG iterations                  =          0 
19:55:28 # of function evaluations           =         15
19:55:28 # of gradient evaluations           =          0
19:55:28 # of Hessian evaluations            =          0
19:55:28 Total program time (secs)           =       0.00127 (     0.001 CPU time)
19:55:28 Time spent in evaluations (secs)    =       0.00047
19:55:28 
19:55:28 Constraint Vector 		     Lagrange Multipliers
19:55:28 ----------------- 		     ---------------------
19:55:28 c[       0] =   4.20820514435e-07,   lambda[       0] =     -0.666666666667
19:55:28 c[       1] =  -1.42523071966e-06,   lambda[       1] =      0.333333333333
19:55:28 
19:55:28 Solution Vector
19:55:28 ---------------
19:55:28 x[       0] =       2.33333408896,   lambda[       2] =                   0
19:55:28 x[       1] =     -0.666666331863,   lambda[       3] =                   0
19:55:28 
19:55:38 =========================== short test summary info ============================
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_add_and_remove_vars_5_knitro_direct - AssertionError: 1.500000828607814 != 1.5 within 7 places (8.286078139185804e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_add_remove_cons_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_duals_5_knitro_direct - AssertionError: 1.000000882731383 != 1 within 7 places (8.827313831005767e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_2_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_4_2_knitro_direct - AssertionError: 1.4142134816662406 != 1.4142135623730951 within 7 places (8.070685453276383e-08 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_fixed_vars_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_immutable_param_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_no_objective_5_knitro_direct - AssertionError: 0.0 != None
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_objective_changes_5_knitro_direct - AssertionError: 1.0000008827313833 != 1 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_param_changes_5_knitro_direct - AssertionError: 1.5000008827313833 != 1.5 within 7 places (8.827313833226214e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_results_infeasible_5_knitro_direct - AssertionError: <TerminationCondition.unknown: 42> not found in {<TerminationCondition.infeasibleOrUnbounded: 8>, <TerminationCondition.provenInfeasible: 6>}
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_scaling_5_knitro_direct - AssertionError: 1.000000882731383 != 1 within 7 places (8.827313831005767e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_stale_vars_5_knitro_direct - AssertionError: False is not true
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_variables_elsewhere2_5_knitro_direct - AssertionError: 8.993019857525455e-07 != 0 within 7 places (8.993019857525455e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_variables_elsewhere_5_knitro_direct - AssertionError: 1.0000008993019858 != 1 within 7 places (8.993019857683748e-07 difference)
19:55:38 FAILED pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py::TestSolvers::test_with_numpy_5_knitro_direct - AssertionError: -0.6666663318632648 != -0.6666666666666666 within 7 places (3.3480340178027035e-07 difference)

Most of the failures are just tolerance problems / the tolerance needs to be loosened.

@mrmundt
Copy link
Contributor

mrmundt commented Sep 19, 2025

One-off failures:

pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers.test_no_objective_5_knitro_direct (from pytest)

Error Message

AssertionError: 0.0 != None

Stacktrace

a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_no_objective_5_knitro_direct>,)
kw = {}

    @wraps(func)
    def standalone_func(*a, **kw):
>       return func(*(a + p.args), **p.kwargs, **kw)

/python3.12/site-packages/parameterized/parameterized.py:620: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:930: in test_no_objective
    self.assertEqual(res.incumbent_objective, None)
E   AssertionError: 0.0 != None

Second one-off:

pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers.test_stale_vars_5_knitro_direct (from pytest)

Error Message

AssertionError: False is not true

Stacktrace

a = (<pyomo.contrib.solver.tests.solvers.test_solvers.TestSolvers testMethod=test_stale_vars_5_knitro_direct>,)
kw = {}

    @wraps(func)
    def standalone_func(*a, **kw):
>       return func(*(a + p.args), **p.kwargs, **kw)
/python3.12/site-packages/parameterized/parameterized.py:620: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyomo/pyomo/contrib/solver/tests/solvers/test_solvers.py:618: in test_stale_vars
    self.assertTrue(m.x.stale)
E   AssertionError: False is not true

@eminyouskn
Copy link
Contributor Author

Thanks @mrmundt for the report. I didn’t run these tests locally since I didn’t have NumPy installed, and in that case, the tests are skipped. I’ll make sure to check them before pushing code from now on.

I do have a question: is there a way to adjust the tolerance for all these tests at once? Ideally, we’d only change it for Knitro, but I imagine that might be more complicated.

Regarding the two remaining failures, I’ve already fixed the one related to the objective. However, I’m not sure how to address the stale one, it’s not clear to me what exactly that test is supposed to check.

Copy link
Contributor

@mrmundt mrmundt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eminyouskn - I realized one thing is definitely missing! Can you please update the docs to include knitro? https://github.com/Pyomo/pyomo/blob/main/doc/OnlineDocs/explanation/experimental/solvers.rst

@eminyouskn
Copy link
Contributor Author

@mrmundt done!

Co-authored-by: Miranda Mundt <55767766+mrmundt@users.noreply.github.com>
@eminyouskn
Copy link
Contributor Author

@blnicho I think the issue with Jenkins was resolved with #3750. So I will update my branch and then we can rerun Jenkins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Review In Progress

Development

Successfully merging this pull request may close these issues.

5 participants